<?php

/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 fdm=marker: */

/**
 * LightBot_Protocol_Default_SocketAdapter 
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category  LightBot
 * @package   LightBot_Protocol_Default
 * @copyright Copyright (c) 2008 Olivier Hoareau <hoareau.olivier@gmail.com>
 * @author    Olivier Hoareau <hoareau.olivier@gmail.com>
 * @license   License http://framework.zend.com/license   New BSD License
 * @version   $Id: SocketAdapter.php 43 2008-05-13 17:02:32Z hoareau.olivier $
 */

require_once dirname(__FILE__) . '/../../ISocketAdapter.php';

// {{{ LightBot_Protocol_Default_SocketAdapter

/**
 * Socket Adapter implementation
 *
 * @category  LightBot
 * @package   LightBot_Protocol_Default
 * @copyright Copyright (c) 2008 Olivier Hoareau <hoareau.olivier@gmail.com>
 * @author    Olivier Hoareau <hoareau.olivier@gmail.com>
 * @license   License http://framework.zend.com/license   New BSD License
 */
class LightBot_Protocol_Default_SocketAdapter implements LightBot_ISocketAdapter
{
    // {{{ open()

    /**
     * Opens a socket connection to the specified host and port
     *
     * @param  string    $host the host
     * @param  integer   $port the port
     * @return resource  the opened socket connection
     * @throws Exception if the socket is null or closed
     */
    public function open($host,$port)
    {
        $socket = fsockopen($host, (int)$port);
        if (!is_resource($socket) || @feof($socket)) {
            throw new Exception("Unable to open socket connection or server closes unexpectedly");
        }
        socket_set_blocking($socket, 0);
        socket_set_timeout($socket , 31536000);
        return $socket;
    }

    // }}}
    // {{{ close()

    /**
     * Closes the specified socket connection
     *
     * @param  resource  $socket the socket to close
     * @throws Exception if the socket is null or closed
     */
    public function close($socket)
    {
        if (!is_resource($socket) || @feof($socket)) {
            throw new Exception("Socket is closed, unable to close socket");
        }
        @fclose($socket);
    }

    // }}}
    // {{{ read()

    /**
     * Reads on the available data on the specified socket
     *
     * @param  resource  $socket the socket to read on
     * @return string    the read data
     * @throws Exception if the socket is null or closed
     */
    public function read($socket)
    {
        if (!is_resource($socket) || @feof($socket)) {
            throw new Exception("Socket closed, unable to read");
        }
        $buffer = '';
        do {
            $line = @fread($socket,4096);
            if($line) $buffer .= $line;
        } while($line!==false && $line!=='');
#        if(strlen($buffer)) echo "<<--- $buffer\n"; 
        return $buffer;
    }

    // }}}
    // {{{ isSocketOpened()

    /**
     * Indicates whether the socket is opened or not
     *
     * @param  resource $socket the socket
     * @return boolean  true if opened false otherwise
     */
    public function isSocketOpened($socket)
    {
        return is_resource($socket) && !@feof($socket);
    }

    // }}}
    // {{{ write()

    /**
     * Writes the specified raw data on the specified socket
     *
     * @param  resource  $socket the socket to write in
     * @param  string    $raw    the raw data to write
     * @return integer   the number of written raw data
     * @throws Exception if the socket is null or closed
     */
    public function write($socket,$raw)
    {
        if (!is_resource($socket) || @feof($socket)) {
            throw new Exception("Socket closed, unable to write");
        }
#        echo "--->> $raw\n"; 
        return @fwrite($socket,$raw);
    }

    // }}}
    // {{{ crypt()

    /**
     * Crypts the specified socket
     *
     * @param  resource  $socket the socket connection to crypt
     * @return boolean   always  true
     * @throws Exception if the socket is null or closed or unable to crypt socket
     */
    public function crypt($socket)
    {
        if (!is_resource($socket) || @feof($socket)) {
            throw new Exception("Socket closed, unable to crypt");
        }
        $meta = stream_get_meta_data($socket);
        socket_set_blocking($socket, 1);
        if (!stream_socket_enable_crypto($socket, TRUE, STREAM_CRYPTO_METHOD_TLS_CLIENT)) throw new Exception("Unable to crypt socket connection");
        socket_set_blocking($socket, $meta["blocked"]);
        return true;
    }

    // }}}
}   

// }}}

/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * c-hanging-comment-ender-p: nil
 * End:
 */
